﻿''
''Copyright Zac McKenzie 2012
''

Imports sxl = System.Xml.Linq
Imports System.Linq
Public Class timerConflicts


    Public Shared Sub determineTimerIssues(ByVal webTvGuide As ozTivoListing, ByVal beyonWizTimerList As List(Of scheduledEvent), ByVal progWatchList As List(Of String))

        For Each tvGuideListing As tvGuideListing In webTvGuide.tvGuideListings_List
            If tvGuideListing.tvGuideScheduledEventsList.Count = 0 Then Continue For '                                    if couldn't download any guide then skip


            wizScheduleCheckerMain.updateStatus("checking timers for matches ", tvGuideListing.tvGuideScheduledEventsList.FirstOrDefault.channel)

            For Each tvGuideScheduledEvent As scheduledEvent In tvGuideListing.tvGuideScheduledEventsList
                If tvGuideScheduledEvent.stopTime < Now Then Continue For 'don't bother looking at past events

                'currently running
                Dim BadTimeInPast As List(Of scheduledEvent) = (From bwT As scheduledEvent In beyonWizTimerList
                                Where bwT.issueCategory <> "C" And bwT.startTime < Now() And bwT.stopTime > Now() And bwT.issueText = ""
                                Let xx = bwT.issueSideEffect("Currently running timer", "", bwT, "G", tvGuideScheduledEvent)
                                Select bwT).ToList

                'find 100% matches
                Dim goodList As List(Of scheduledEvent) = (From bwT As scheduledEvent In beyonWizTimerList
                                                    Where tvGuideScheduledEvent.channel = bwT.channel And
                                                          tvGuideScheduledEvent.progName.ToUpper = bwT.progName.ToUpper And
                                                          tvGuideScheduledEvent.startTime = bwT.startTime And
                                                          tvGuideScheduledEvent.stopTime = bwT.stopTime And
                                                          bwT.issueCategory <> "C" And bwT.issueCategory <> "G"
                                                          Let yy = bwT.issueSideEffect("Good Prog/ Time", "", bwT, "G", tvGuideScheduledEvent)
                                                          Let y1 = tvGuideScheduledEvent.issueSideEffect("Good Prog/ Time", "", bwT, "G", tvGuideScheduledEvent)
                                                    Select bwT).ToList

            Next tvGuideScheduledEvent
        Next tvGuideListing


        For Each tvGuideListing As tvGuideListing In webTvGuide.tvGuideListings_List
            If tvGuideListing.tvGuideScheduledEventsList.Count = 0 Then Continue For '                                    if couldn't download any guide then skip


            wizScheduleCheckerMain.updateStatus("checking timers for mismatches ", tvGuideListing.tvGuideScheduledEventsList.FirstOrDefault.channel)

            For Each tvGuideScheduledEvent As scheduledEvent In tvGuideListing.tvGuideScheduledEventsList
                If tvGuideScheduledEvent.stopTime < Now Then Continue For 'don't bother looking at past events
                'program and channel are good but time is wrong
                Dim goodProgBadTime As List(Of scheduledEvent) = (From bwT As scheduledEvent In beyonWizTimerList
                                                    Where tvGuideScheduledEvent.channel = bwT.channel And
                                                          tvGuideScheduledEvent.progName.ToUpper = bwT.progName.ToUpper And
                                                          tvGuideScheduledEvent.startTime.Date = bwT.startTime.Date And
                                                          tvGuideScheduledEvent.issueText = "" And bwT.issueText = ""
                                                          Let xx = bwT.issueSideEffect("Good Prog/ Slightly Bad Time - ", bwT.startTime.TimeOfDay.ToString, bwT, "GGW", tvGuideScheduledEvent)
                                                          Let x1 = tvGuideScheduledEvent.issueSideEffect("Good Prog/ Slightly Bad Time - ", tvGuideScheduledEvent.startTime.TimeOfDay.ToString,
                                                                                                         bwT, "GGW", tvGuideScheduledEvent)
                                                    Select bwT).ToList

                'program and channel are good but date/time is wrong
                Dim goodProgBadDate As List(Of scheduledEvent) = (From bwT As scheduledEvent In beyonWizTimerList
                                                    Where tvGuideScheduledEvent.channel = bwT.channel And
                                                          tvGuideScheduledEvent.progName.ToUpper = bwT.progName.ToUpper And
                                                          tvGuideScheduledEvent.issueText = "" And bwT.issueText = ""
                                                          Let xx = bwT.issueSideEffect("Good Prog/ Bad DateTime - ", tvGuideScheduledEvent.startTime.ToString, bwT, "GGW", tvGuideScheduledEvent)
                                                          Let x1 = tvGuideScheduledEvent.issueSideEffect("Good Prog/ Bad DateTime - ", bwT.startTime.ToString, bwT, "GGW", tvGuideScheduledEvent)
                                                    Select bwT).ToList

                'program is good, channel wrong
                Dim goodProgBadChannel As List(Of scheduledEvent) = (From bwT As scheduledEvent In beyonWizTimerList
                                                    Where tvGuideScheduledEvent.channel <> bwT.channel And
                                                          tvGuideScheduledEvent.progName.ToUpper = bwT.progName.ToUpper And
                                                          tvGuideScheduledEvent.startTime.Date = bwT.startTime.Date And
                                                          tvGuideScheduledEvent.issueText = "" And bwT.issueText = ""
                                                          Let xx = bwT.issueSideEffect("BadChannel/ Same Day - ", tvGuideScheduledEvent.channel, bwT, "WGW", tvGuideScheduledEvent)
                                                          Let x1 = tvGuideScheduledEvent.issueSideEffect("BadChannel/ Same Day - ", bwT.channel, bwT, "WGW", tvGuideScheduledEvent)
                                                    Select bwT).ToList

                'program is good, channel/ date wrong
                Dim goodProgBadChannelDate As List(Of scheduledEvent) = (From bwT As scheduledEvent In beyonWizTimerList
                                                    Where tvGuideScheduledEvent.channel <> bwT.channel And
                                                          tvGuideScheduledEvent.progName.ToUpper = bwT.progName.ToUpper And
                                                          tvGuideScheduledEvent.startTime.Date = bwT.startTime.Date And tvGuideScheduledEvent.issueText = "" And bwT.issueText = ""
                                                          Let xx = bwT.issueSideEffect("BadChannel/ Diff Day - ", tvGuideScheduledEvent.channel & " " & tvGuideScheduledEvent.startTime.ToString, bwT,
                                                                                       "WGW", tvGuideScheduledEvent)
                                                          Let x1 = tvGuideScheduledEvent.issueSideEffect("BadChannel/ Diff Day - ", bwT.channel & " " & bwT.startTime.ToString, bwT,
                                                                                                         "WGW", tvGuideScheduledEvent)
                                                    Select bwT).ToList
                'good channel/ date, bad program 
                Dim goodChannelDateBadProg As List(Of scheduledEvent) = (From bwT As scheduledEvent In beyonWizTimerList
                                    Where tvGuideScheduledEvent.channel = bwT.channel And
                                          tvGuideScheduledEvent.progName.ToUpper <> bwT.progName.ToUpper And
                                          tvGuideScheduledEvent.startTime = bwT.startTime And
                                          tvGuideScheduledEvent.stopTime = bwT.stopTime And tvGuideScheduledEvent.issueText = "" And bwT.issueText = ""
                                          Let yy = bwT.issueSideEffect("Good Event/ Bad Name -", tvGuideScheduledEvent.progName, bwT, "GWG", tvGuideScheduledEvent)
                                          Let y1 = tvGuideScheduledEvent.issueSideEffect("Good Event/ Bad Name -", bwT.progName, bwT, "GWG", tvGuideScheduledEvent)
                                    Select bwT).ToList

                'bad program
                Dim badProgram As List(Of scheduledEvent) = (From bwT As scheduledEvent In beyonWizTimerList
                           Where tvGuideScheduledEvent.channel = bwT.channel And
                                 tvGuideScheduledEvent.progName.ToUpper <> bwT.progName.ToUpper And
                                 bwT.startTime < tvGuideScheduledEvent.stopTime And bwT.stopTime > tvGuideScheduledEvent.startTime And
                                 tvGuideScheduledEvent.issueText = "" And bwT.issueText = ""
                                 Let xx = bwT.issueSideEffect("BadProgram - ", tvGuideScheduledEvent.progName, bwT, "E", tvGuideScheduledEvent)
                                 Let x1 = tvGuideScheduledEvent.issueSideEffect("BadProgram - ", bwT.progName, bwT, "E", tvGuideScheduledEvent)
                           Select bwT).ToList

                'bad In the past
                Dim BadTimeInPast As List(Of scheduledEvent) = (From bwT As scheduledEvent In beyonWizTimerList
                                Where bwT.stopTime < Now And bwT.issueText = ""
                                Let xx = bwT.issueSideEffect("Bad Time - You've missed it", "", bwT, "E", tvGuideScheduledEvent)
                                Select bwT).ToList
            Next tvGuideScheduledEvent
        Next tvGuideListing

        Dim sortedTVGuide As List(Of scheduledEvent) = (From tvPL In webTvGuide.tvGuideListings_List From se As scheduledEvent In tvPL.tvGuideScheduledEventsList Order By se.startTime Select se).ToList

        wizScheduleCheckerMain.updateStatus("Looking for programs in the watch list", "")
        For Each tvGuideScheduledEvent As scheduledEvent In sortedTVGuide
            If tvGuideScheduledEvent.stopTime < Now Then Continue For 'don't bother looking at past events

            If tvGuideScheduledEvent.issueText = "" And progWatchList.Contains(tvGuideScheduledEvent.progName.ToUpper) Then
                addEventAndCheckConflict(beyonWizTimerList, progWatchList, tvGuideScheduledEvent, "WatchListMatch - ")

            End If
        Next tvGuideScheduledEvent

        wizScheduleCheckerMain.updateStatus("Looking for programs in the category list", "")
        For Each tvGuideScheduledEvent As scheduledEvent In sortedTVGuide
            If tvGuideScheduledEvent.stopTime < Now Then Continue For 'don't bother looking at past events

            If tvGuideScheduledEvent.issueText = "" And (config.catWatchList.Contains(tvGuideScheduledEvent.category1) Or config.catWatchList.Contains(tvGuideScheduledEvent.category2) Or config.catWatchList.Contains(tvGuideScheduledEvent.category3) Or config.catWatchList.Contains(tvGuideScheduledEvent.category4) Or config.catWatchList.Contains(tvGuideScheduledEvent.category5)) Then
                addEventAndCheckConflict(beyonWizTimerList, progWatchList, tvGuideScheduledEvent, "WatchListMatch - ")

            End If
        Next tvGuideScheduledEvent

        wizScheduleCheckerMain.updateStatus("Looking for programs above ratings threshold of ", config.ratingThreashold)
        Dim rt As Integer
        Try
            rt = config.ratingThreashold
        Catch ex As Exception
            rt = 7
        End Try
        For Each tvGuideScheduledEvent As scheduledEvent In sortedTVGuide
            If tvGuideScheduledEvent.stopTime < Now Then Continue For 'don't bother looking at past events

            For r As Integer = rt To 10
                Dim sr = r.ToString & "/10"
                If tvGuideScheduledEvent.issueText = "" And (tvGuideScheduledEvent.starRating = sr) Then

                    'conflicts program
                    Dim confl As List(Of scheduledEvent) = (From bwT As scheduledEvent In beyonWizTimerList
                               Where tvGuideScheduledEvent.issueCategory <> "E" And tvGuideScheduledEvent.issueCategory <> "E" And
                                     Not (tvGuideScheduledEvent.progName = bwT.progName And tvGuideScheduledEvent.channel = bwT.channel And tvGuideScheduledEvent.startTime = bwT.startTime And tvGuideScheduledEvent.stopTime = bwT.stopTime) And
                                     bwT.startTime < tvGuideScheduledEvent.stopTime And bwT.stopTime > tvGuideScheduledEvent.startTime
                               Select bwT).ToList

                    tvGuideScheduledEvent.issueSideEffect("RatingMatch - ", tvGuideScheduledEvent.progName, tvGuideScheduledEvent, "R")
                    Dim tempSE As scheduledEvent = tvGuideScheduledEvent.clone
                    beyonWizTimerList.Add(tempSE)

                    If confl.Count >= config.noTimers Then

                        tempSE.issueCategory = "C"
                        tempSE.issueText = "Conflict with " & confl.First.progName
                    End If

                End If
            Next r

        Next tvGuideScheduledEvent

        'Next tvProgramList

    End Sub

    Public Shared Function addEventAndCheckConflict(ByVal beyonWizTimerList As List(Of scheduledEvent), ByVal progWatchList As List(Of String), ByRef tvGuideScheduledEvent As scheduledEvent, ByVal action As String) As scheduledEvent

        Dim tvSE = tvGuideScheduledEvent
        'conflicts program
        Dim confl As List(Of scheduledEvent) = (From bwT As scheduledEvent In beyonWizTimerList
                   Where bwT.issueCategory <> "E" And bwT.issueCategory <> "C" And
                         Not (tvSE.progName = bwT.progName And tvSE.channel = bwT.channel And tvSE.startTime = bwT.startTime And tvSE.stopTime = bwT.stopTime) And
                         bwT.startTime < tvSE.stopTime And bwT.stopTime > tvSE.startTime
                   Select bwT).ToList

        Dim tempSE As scheduledEvent = tvGuideScheduledEvent.clone
        beyonWizTimerList.Add(tempSE)
        tvGuideScheduledEvent.issueSideEffect(action, "", tvGuideScheduledEvent, "R", tempSE)
        tempSE.issueSideEffect(action, "", tempSE, "R", tvGuideScheduledEvent)

        If confl.Count >= config.noTimers Then

            Dim i1 As Integer = progWatchList.IndexOf(confl.First.progName.ToUpper)
            Dim i2 As Integer = progWatchList.IndexOf(tvGuideScheduledEvent.progName.ToUpper)
            ' the newly added se should be chosen as the conflict if: 
            '   it is not in the watch list but the other one is in the watch list OR
            '   both are but the new one is lower priority Or 
            '   the other one is currently running (because I don't want to muck around with running timers)
            If (i1 <> -1 And i1 < i2) Or i2 = -1 Or (confl.First.startTime < Now And confl.First.stopTime > Now) Then

                tempSE.issueCategory = "C"
                tempSE.issueText = "Conflict with " & confl.First.progName
            Else
                confl.First.issueCategory = "C"
                confl.First.issueText = "Conflict with " & tvGuideScheduledEvent.progName
            End If
        End If
        Return tempSE
    End Function

    Public Shared Sub identifyConflicts(ByVal webTvGuide As ozTivoListing, ByVal beyonWizTimerList As List(Of scheduledEvent), ByVal progWatchList As List(Of String))
        'when adding to the timer list I want the following order:
        '1) prog watch lists are highest prority so -
        '   - check no conflict between watch list items - if there is go top to bottom
        '   - remove non-watch list items which conflict     
        wizScheduleCheckerMain.updateStatus("checking for conflicts ", "")
        Dim conflicts = (From a In beyonWizTimerList From b In beyonWizTimerList
                         Let xyz = debugState(a.progName, b.progName)
                         Where (a.issueCategory <> "E" And b.issueCategory <> "E" And a.issueCategory <> "C" And b.issueCategory <> "C" And
                                Not (a.progName = b.progName And a.channel = b.channel And a.startTime = b.startTime And a.stopTime = b.stopTime) And
                                a.startTime < b.stopTime And a.stopTime > b.startTime) And a.startTime >= b.startTime
                                Select aProg = a.progName, aStart = a.startTime, aStop = a.stopTime,
                                       bProg = b.progName, bStart = b.startTime, bStop = b.stopTime, conflictA = a, conflictB = b).ToList
        wizScheduleCheckerMain.updateStatus("checking for conflicts ", " Number found: " & conflicts.count)
        If conflicts.count > 0 Then
            Dim s As String = ""
            For Each cflt As Object In conflicts
                s = s & (cflt.aProg.padright(25, " ")).ToString.Substring(0, 25) & cflt.aStart & cflt.aStop & vbLf & (cflt.bProg.padright(25, " ")).ToString.Substring(0, 25) & cflt.bStart & cflt.bStop & vbLf & vbLf
                cflt.conflictB.issueCategory = "C"
                cflt.conflictB.issueText = "Conflict with " & cflt.conflicta.progname
            Next
            MsgBox(s)
        End If
    End Sub

    Private Shared Function debugState(ByVal s As String, ByVal s2 As String) As String
        Return s
    End Function
End Class
